using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using HuaXianQu.ProtoBuffEx.Runtime;
using UnityEngine;

namespace HuaXianQu.ProtoBuffEx.ToolEditor
{
    public class ExcelData
    {
        private ExcelData(object content)
        {
            Content = content;
        }

        public object Content { get; set; }
        public string VariableName { get; set; }
        public string Data { get; set; }
        public int DataIndex { get; set; } = -1;
        public bool IsVariable { get; set; }
        public bool IsChild => DataChilds.Count > 0 || chilDictionary.Count > 0;
        public List<ExcelData> DataChilds { get; set; } = new();
        private Dictionary<string, ExcelData> chilDictionary = new();
        public VariableInfo CurVariableInfo { get; set; }
        private bool IsRecycle { get; set; } = false;
        public static int CacheCount { get; set; }

        private List<ExcelData> Caches = new List<ExcelData>();
        static Lazy<ExcelData> LazyData = new(() => new ExcelData(null));

        public static ExcelData GetExcelData(object content)
        {
            CacheCount++;
            return LazyData.Value.GetOrCreateExcelData(content);
        }

        public bool GetMapKey(out string mapKey)
        {
            mapKey = null;
            if (CurVariableInfo != null && CurVariableInfo.MapKey != null)
            {
                mapKey = CurVariableInfo.MapKey;
                return true;
            }

            return false;
        }

        public static void Reset()
        {
            ProtoDebug.LogWarning(@"当前使用的ExcelData数量：{ CacheCount}");
            CacheCount = 0;
            LazyData = new(() => new ExcelData(null));
        }

        private ExcelData GetOrCreateExcelData(object content)
        {
            ExcelData temp;
            if (Caches.Count > 0)
            {
                temp = Caches[^1];
                temp.Content = content;
                Caches.RemoveAt(Caches.Count - 1);
                return temp;
            }
            else
            {
                temp = new ExcelData(content);
            }

            temp.IsRecycle = false;
            return temp;
        }


        private void Parse(string data)
        {
            Match match = Regex.Match(data, @"[\t\s\n]*([\w]*)[\t\s\n]*:[\t\s\n]*([\w\\W]*)");
            if (match.Length > 0)
            {
                if (match.Groups.Count == 3)
                {
                    VariableName = match.Groups[1].Value.Trim();
                    Data = match.Groups[2].Value;

                    IsVariable = !string.IsNullOrWhiteSpace(VariableName);
                    return;
                }
            }

            Data = data;
            IsVariable = false;
        }

        public bool AddChild(ExcelData data)
        {
            if (data.IsVariable)
            {
                return chilDictionary.TryAdd(data.VariableName, data);
            }

            DataChilds.Add(data); //非定义变量名称按顺序解析变量
            return false;
        }

        public bool GetData(string name, out ExcelData data)
        {
            return chilDictionary.TryGetValue(name, out data);
        }

        public void SetChild(string data, int index)
        {
            var temp = GetOrCreateExcelData(this);
            temp.Data = data;
            temp.DataIndex = index;
            DataChilds.Add(temp);
        }

        public void SetClassChild(string data, int index)
        {
            var temp = GetOrCreateExcelData(this);
            temp.Data = data;
            temp.DataIndex = index;
            temp.Parse(data);
            if (temp.IsVariable)
            {
                IsVariable = true;
            }

            AddChild(temp);
        }

        public void Recycle()
        {
            if (IsRecycle)
            {
                return;
            }

            IsRecycle = true; //防止循环嵌套导致死循环
            CacheCount--;
            VariableName = null;
            Data = null;
            DataIndex = -1;
            IsVariable = false;
            Content = null;
            CurVariableInfo = null;
            foreach (var data in DataChilds)
            {
                data.Recycle();
            }

            chilDictionary.Clear();
            DataChilds.Clear();
            LazyData.Value.Caches.Add(this);
        }

        public override string ToString()
        {
            return Data;
        }
    }
}